package com.bjsxt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjsxt.domain.Market;
import com.bjsxt.domain.TradeArea;
import com.bjsxt.domain.UserFavoriteMarket;
import com.bjsxt.mapper.TradeAreaMapper;
import com.bjsxt.model.MergeDeptVo;
import com.bjsxt.model.TradeAreaMarketVo;
import com.bjsxt.model.TradeMarketVo;
import com.bjsxt.service.MarketService;
import com.bjsxt.service.TradeAreaService;
import com.bjsxt.service.UserFavoriteMarketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class TradeAreaServiceImpl extends ServiceImpl<TradeAreaMapper, TradeArea> implements TradeAreaService {
    /**
     * 交易市场业务层对象
     */
    @Autowired
    private MarketService marketService;
    /**
     * 用户收藏业务层对象
     */
    @Autowired
    private UserFavoriteMarketService userFavoriteMarketService;

    /**
     * 分页查询交易区域数据
     *
     * @param page   分页对象<TradeArea>
     * @param name   交易区名称
     * @param status 状态
     * @return 查询出的交易区域分页数据
     */
    @Override
    public Page<TradeArea> pageByNameAndStatus(Page<TradeArea> page, String name, Byte status) {
        // 调用分页方法进行数据的查询
        return page(page, new LambdaQueryWrapper<TradeArea>().like(!StringUtils.isEmpty(name), TradeArea::getName, name).eq(status != null, TradeArea::getStatus, status));
    }

    /**
     * 根据状态查询所有的交易区域
     *
     * @param status 状态：0: 无效 1:有效
     * @return 交易区域集合
     */
    @Override
    public List<TradeArea> listByStatus(Byte status) {
        // 动态构建 sql 查询条件
        return list(new LambdaQueryWrapper<TradeArea>().eq(TradeArea::getStatus, status));
    }

    /**
     * 获取交易区域和区域下的市场
     *
     * @return 交易区域和区域下的市场集合数据
     */
    @Override
    public List<TradeAreaMarketVo> listTradeAreaMarkets() {
        // 创建需要返回的对象
        List<TradeAreaMarketVo> tradeAreaMarketVos = new ArrayList<TradeAreaMarketVo>();
        // 查询所有的交易区域
        List<TradeArea> tradeAreas = list(new LambdaQueryWrapper<TradeArea>().eq(TradeArea::getStatus, 1).orderByAsc(TradeArea::getSort));
        // 如果查询的交易区域是空的则直接返回空集合
        if (CollectionUtils.isEmpty(tradeAreas)) return Collections.emptyList();
        // 循环交易区域将数据放入到 vo 对象中
        for (TradeArea tradeArea : tradeAreas) {
            // 创建需要返回的 TradeAreaMarketVo 对象
            TradeAreaMarketVo tradeAreaMarketVo = new TradeAreaMarketVo();
            // 设置交易区域名称
            tradeAreaMarketVo.setAreaName(tradeArea.getName());
            // 做交易市场的查询
            List<Market> markets = marketService.listByTradeAreaId(tradeArea.getId(), (byte) 1);
            // 将 Market 转换为 Market TradeMarketVo
            List<TradeMarketVo> tradeMarketVos = marketsToTradeMarketVos(markets);
            // 将解析后的值放入到 tradeAreaMarketVo 对象
            tradeAreaMarketVo.setMarkets(tradeMarketVos);
            // 将数据放入到集合对象中
            tradeAreaMarketVos.add(tradeAreaMarketVo);
        }
        // 返回构建完成的数据
        return tradeAreaMarketVos;
    }

    /**
     * 根据用户 id 查询用户的收藏市场列表
     *
     * @param userId 用户 id
     * @return 交易区域和区域下的市场集合数据
     */
    @Override
    public List<TradeAreaMarketVo> getFavoriteByUserId(Long userId) {
        // 根据用户 id 获取用户的收藏列表
        List<UserFavoriteMarket> userFavoriteMarkets = userFavoriteMarketService.listByUserId(userId);
        // 如果查询的数据集合是空，则直接返回空集合
        if (CollectionUtils.isEmpty(userFavoriteMarkets)) return Collections.emptyList();
        // 获取交易市场 id 集合
        List<Long> marketIds = userFavoriteMarkets.stream().map(UserFavoriteMarket::getMarketId).collect(Collectors.toList());
        // 根据市场的 id 集合查询市场数据
        List<Market> markets = marketService.listByIds(marketIds);
        // 将 Market 转换为 Market TradeMarketVo
        List<TradeMarketVo> tradeMarketVos = marketsToTradeMarketVos(markets);
        // 创建需要返回的 vo 对象
        TradeAreaMarketVo tradeAreaMarketVo = new TradeAreaMarketVo();
        // 交易区名称
        tradeAreaMarketVo.setAreaName("收藏");
        tradeAreaMarketVo.setMarkets(tradeMarketVos);
        // 返回构建完成的收藏对象
        return Collections.singletonList(tradeAreaMarketVo);
    }

    /**
     * 将交易市场转换为 交易市场 Vo 对象
     *
     * @param markets 交易市场集合数据
     * @return 交易市场 Vo 对象集合
     */
    private List<TradeMarketVo> marketsToTradeMarketVos(List<Market> markets) {
        // 创建需要返回的 vo 对象
        List<TradeMarketVo> tradeMarketVos = new ArrayList<TradeMarketVo>();
        // 循环遍历市场数据
        for (Market market : markets) {
            // 创建需要返回的 TradeMarketVo 对象
            TradeMarketVo tradeMarketVo = new TradeMarketVo();
            // 设置对应的属性值
            tradeMarketVo.setSymbol(market.getSymbol());
            tradeMarketVo.setName(market.getName());
            tradeMarketVo.setImage(market.getImg());
            tradeMarketVo.setBuyFeeRate(market.getFeeBuy());
            tradeMarketVo.setSellFeeRate(market.getFeeSell());
            tradeMarketVo.setPriceScale(market.getPriceScale());
            tradeMarketVo.setNumScale(market.getNumScale());
            tradeMarketVo.setNumMin(market.getNumMin());
            tradeMarketVo.setNumMax(market.getNumMax());
            tradeMarketVo.setTradeMin(market.getTradeMin());
            tradeMarketVo.setTradeMax(market.getTradeMax());
            // TODO: 这里需要用到 K 线的数据以后实现
            tradeMarketVo.setPrice(null);
            tradeMarketVo.setPriceUnit(null);
            tradeMarketVo.setCnyPrice(null);
            tradeMarketVo.setCoinCnyPrice(null);
            tradeMarketVo.setMergeDepth(parseMergeDepth(market.getMergeDepth()));
            tradeMarketVo.setHigh(null);
            tradeMarketVo.setLow(null);
            tradeMarketVo.setVolume(null);
            tradeMarketVo.setAmount(null);
            tradeMarketVo.setChange(0.0);
            tradeMarketVo.setSort(market.getSort());
            // 将数据添加到集合中
            tradeMarketVos.add(tradeMarketVo);
        }
        // 返回构建完成的数据
        return tradeMarketVos;
    }

    /**
     * 解析交易市场的合并深度解析为一个 MergeDeptVo 集合
     *
     * @param mergeDepth 合并深度字符串
     * @return MergeDeptVo 集合
     */
    private List<MergeDeptVo> parseMergeDepth(String mergeDepth) {
        // 床架返回的集合对象
        List<MergeDeptVo> mergeDeptVos = new ArrayList<MergeDeptVo>();
        // 将字符串数组进行 , 分割为 list 对象
        List<String> mergeDepthList = Arrays.asList(mergeDepth.split(","));
        // 如果获取的值不是三则数据有问题
        if (mergeDepthList.size() != 3) throw new IllegalArgumentException("合并深度不合法");
        // 对 list 进行排序
        mergeDepthList.sort(String::compareTo);
        // 对数据进行添加
        mergeDeptVos.add(new MergeDeptVo("MIN", getTruthMergeDepth(Byte.parseByte(mergeDepthList.get(0)))));
        mergeDeptVos.add(new MergeDeptVo("DEFAULT", getTruthMergeDepth(Byte.parseByte(mergeDepthList.get(1)))));
        mergeDeptVos.add(new MergeDeptVo("MAX", getTruthMergeDepth(Byte.parseByte(mergeDepthList.get(2)))));
        // 返回构建完成的数据对象
        return mergeDeptVos;
    }

    /**
     * 转换为真实的合并深度值
     *
     * @param scale 合并深度值
     * @return 1 = 1/10 2=1/100 返回小数的 BigDecimal 对象
     */
    private BigDecimal getTruthMergeDepth(Byte scale) {
        // 获取需要需要整除的深度值 10 的 scale 次方
        return BigDecimal.ONE.divide(new BigDecimal(Math.pow(10, scale))).setScale(scale, RoundingMode.HALF_UP);
    }
}
